 #include <xpm/minus.xpm>
 #include <xpm/netpad20.xpm>
 #include <xpm/exit20.xpm>
 #include <xpm/android.xpm>
 #include <xpm/gmail.xpm>
 #include <xpm/gtalk.xpm>
 #include <xpm/apple.xpm>
 #include <xpm/sync.xpm>
 #include <xpm/tag.xpm>
 #include <xpm/block.xpm>
 #include <xpm/hide.xpm>
 #include <xpm/colour.xpm>
 #include <xpm/menu.xpm>
 #include <xpm/exit.xpm>
 #include <xpm/red.xpm>
 #include <xpm/green.xpm>
 #include <xpm/invisible.xpm>
 #include <xpm/orange.xpm>
 #include <xpm/close.xpm>
 #include <xpm/minimize.xpm>
 #include <xpm/facebook.xpm>
 #include <xpm/plus.xpm>
 
 #include "controls.h"
 #include "common.h"
 #include "jabber.h"
 #include "ftp.h"
 #include "netpad.h"
 #include "util.h"

 wxString rle_encode(wxString& b64bytes, unsigned int iLen);
 
 wxColour g_colour;

 extern void *m_ErrPopUp;
 extern connection c_list[];
 
 BEGIN_EVENT_TABLE(QTab, wxWindow)
    EVT_RIGHT_DOWN(QTab::OnRightDown)
    EVT_LEFT_DOWN(QTab::OnLeftDown)
    EVT_LEFT_UP(QTab::OnLeftUp)
    EVT_RIGHT_DOWN(QTab::rightClick)
    EVT_KEY_DOWN(QTab::keyPressed)
    EVT_KEY_UP(QTab::keyReleased)
    EVT_MOUSEWHEEL(QTab::mouseWheelMoved)
    EVT_PAINT(QTab::OnPaint)
    EVT_ERASE_BACKGROUND(QTab::OnEraseBackground)
 END_EVENT_TABLE()

 BEGIN_EVENT_TABLE(QLine, wxWindow)
    EVT_PAINT(QLine::OnPaint)
    EVT_ERASE_BACKGROUND(QLine::OnEraseBackground)
 END_EVENT_TABLE()

 BEGIN_EVENT_TABLE(TransientPopup,wxPopupTransientWindow)
    EVT_SET_FOCUS( TransientPopup::OnSetFocus )
    EVT_KILL_FOCUS( TransientPopup::OnKillFocus )
 END_EVENT_TABLE()

 BEGIN_EVENT_TABLE(TaskBarBaloon, wxFrame)
    EVT_PAINT(TaskBarBaloon::OnPaint)
    EVT_LEFT_DOWN(TaskBarBaloon::OnClick)
    EVT_TIMER(TIMER_BALOON,TaskBarBaloon::OnTimerTick)
 END_EVENT_TABLE()

 void
  get_screen(wxImage *image, wxPoint sp, wxPoint ep)
 {
   wxScreenDC sdc;
   wxMemoryDC mdc;

   int w = ep.x - sp.x;
   int h = ep.y - sp.y;
   
   wxBitmap bitmap(w,h); 

   mdc.SelectObject(bitmap);

   mdc.Blit(0, 0, w, h, &sdc, sp.x, sp.y);

   mdc.SelectObject(wxNullBitmap); 

   *image = bitmap.ConvertToImage();
 }

 QEdit::QEdit(wxWindow      * parent,
              wxWindowID      id,
              const wxString& value,
              const wxPoint&  pos,
              const wxSize&   size,
              long            style,
              const wxValidator& validator,
              const wxString& name)
        : wxTextCtrl(parent, id, value, pos, size, style, validator, name)
 {
   toRestore = 0;
   sizer = 0;
   Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(QEdit::OnKeyDown));      
 }

 void
  QEdit::QEdit_Hide(void)
 {
   Hide();

   if (toRestore) {
     toRestore->Show();
   }

   if (sizer) {
     sizer->Layout();
   }
 }

 void
  QEdit::OnKeyDown(wxKeyEvent& e) 
 {
   if (e.GetKeyCode() == WXK_ESCAPE) {
    QEdit_Hide();
   }

   e.Skip();
 }

////////////////////

 QText::QText(wxWindow*       parent,
              wxWindowID      id,
              const wxString& label,
              const wxPoint&  pos,
              const wxSize&   size,
              long            style,
              const wxString& name)
        :wxStaticText(parent, id, label, pos, size, style, name) 
 {
   SetBackgroundStyle(wxBG_STYLE_CUSTOM);
   this->Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(QText::OnEraseBackGround));
   this->Connect(wxEVT_PAINT, wxPaintEventHandler(QText::OnPaint));
 }

 void
  QText::OnEraseBackGround(wxEraseEvent& WXUNUSED(e)) 
 { 

 }
         
 void
  QText::OnPaint(wxPaintEvent& WXUNUSED(e))
 {
   wxPaintDC dc(this);

   dc.DrawText(m_label, 0, 0);
 }

 void
  QText::SetLabel(const wxString& label)
 {
   wxClientDC dc(this);

   dc.Clear();

   SetSize(GetTextExtent(label));

   Refresh();

   dc.DrawText(m_label = label, 0, 0);
 }

////////////////////

 QBitmap::QBitmap(wxWindow*       parent,
                  wxWindowID      id,
                  const wxBitmap& bitmap,
                  const wxPoint&  pos = wxDefaultPosition,
                  const wxSize&   size = wxDefaultSize,
                  long            style = 0,
                  const wxString& name = wxEmptyString) 
          : wxStaticBitmap(parent, id, bitmap, pos, size, style, name)
 {
   m_data = 0;

   if (!name.Cmp("bitmap_close")  || 
       !name.Cmp("bitmap_minus")  ||
       !name.Cmp("chat_close")    ||
       !name.Cmp("bitmap_buddy")  ||
       !name.Cmp("bitmap_avatar")) {

     SetCursor(wxCURSOR_HAND);
   }
  
   this->Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(QBitmap::OnEraseBackGround));
   this->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(QBitmap::OnLeftDown), NULL, this);
   this->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(QBitmap::OnLeftUp), NULL, this);
   this->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(QBitmap::OnRightUp), NULL, this);
   this->Connect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(QBitmap::OnEnterWindow), NULL, this);
   this->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(QBitmap::OnLeaveWindow), NULL, this);
   this->Connect(wxEVT_PAINT, wxPaintEventHandler(QBitmap::OnPaint));
   this->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(QBitmap::OnLeftDClick), NULL, this);
   this->Connect(wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEventHandler(QBitmap::OnMouseCaptureLost), NULL, this);
   this->Connect(wxEVT_MOTION, wxMouseEventHandler(QBitmap::OnMotion));
 }

 void 
  QBitmap::OnMotion (wxMouseEvent& WXUNUSED(e))
 {

 }

 void
  QBitmap::OnEnterWindow(wxMouseEvent& e)
 {
   wxClientDC dc(this);

   wxString name = GetName();

   if (!name.Cmp("bitmap_minus")) {

     dc.GradientFillLinear(GetClientRect(), wxColour(225,225,0), *wxWHITE, wxSOUTH);

   } else if (!name.Cmp("bitmap_close") || 
              !name.Cmp("chat_close") ) {

     wxRect rect = GetClientRect();

     rect.SetWidth(9); /* hard coded; this is the width of the broken square */

     dc.GradientFillLinear(rect, g_colour, *wxWHITE, wxEAST);

   } else if (!name.CmpNoCase("bitmap_buddy") && 
              !e.Moving()) {

     Jabber *j = (Jabber *)(GetParent()->GetParent());

     if (j->j_hover) {
       j->update_title_bar((IMBuddy *)m_data, 0);
     }

   } else if (!name.CmpNoCase("bitmap_status")) {

     SetCursor(wxNullCursor);

   } else {

     return;
   }   

   dc.DrawBitmap(this->GetBitmap(), 0, 0, true);
 }

 void
  QBitmap::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(e))
 {
   // don't call event.Skip() here...
 }

 void
  QBitmap::OnLeftDown(wxMouseEvent& e) 
 {
   SetFocus();
   e.Skip();
 }

 void
  QBitmap::OnLeftUp(wxMouseEvent& e)
 {
   wxString name = ((wxWindow *)e.GetEventObject())->GetName();

   if (!name.CmpNoCase("chat_close")) {

     ((wxDialog *)GetParent())->HideWithEffect(wxSHOW_EFFECT_BLEND, 150);
     GetParent()->Close();

   } else if (!name.CmpNoCase("bitmap_close")) {

     if (GetParent()->GetParent()) {

       GetParent()->Close(true);   
   
     } else {
  
       GetParent()->Show(false);
     }

   } else if (!name.CmpNoCase("bitmap_minus")) {

     ((wxDialog *)GetParent())->Iconize();

   } else if (!name.CmpNoCase("bitmap_buddy")) {

     if (!e.Moving()) {

       Jabber *j = (Jabber *)(GetParent()->GetParent());

       j->j_hover = true;

       j->update_title_bar((IMBuddy *)m_data, 0);
     }
   }
 }

 void
  QBitmap::OnEraseBackGround(wxEraseEvent&  WXUNUSED(e)) 
 {

 }

 void
  QBitmap::OnPaint(wxPaintEvent& WXUNUSED(e))
 {
   if (GetBitmap().IsOk()) {
     wxPaintDC dc(this);
     dc.DrawBitmap(GetBitmap(), 0, 0, true); 
   }
 }

 void 
  QBitmap::OnRightUp(wxMouseEvent& e)
 {
   if (!(GetName().CmpNoCase("bitmap_buddy"))) {

     wxMenu *menu = new wxMenu();

     wxMenuItem *itemTag = new wxMenuItem(menu, POPUP_BUDDY_TAG, wxString(_("Tag for Status Change Alerts")) , wxEmptyString, wxITEM_NORMAL);
     itemTag->SetBitmap(wxBitmap(tag_xpm));
     menu->Append(itemTag);

     wxMenuItem *itemAutoReply = new wxMenuItem(menu, POPUP_BUDDY_AUTOREPLY, wxString(_("Set Automatic Reply")) , wxEmptyString, wxITEM_NORMAL);
     itemAutoReply->SetBitmap(wxBitmap(sync_xpm));
     menu->Append(itemAutoReply);

     menu->AppendSeparator();

     wxMenuItem *itemHide = new wxMenuItem(menu, POPUP_BUDDY_HIDE, wxString(_("Hide")) , wxEmptyString, wxITEM_NORMAL);
     itemHide->SetBitmap(wxBitmap(hide_xpm));
     menu->Append(itemHide);

     wxMenuItem *itemBlock = new wxMenuItem(menu, POPUP_BUDDY_BLOCK, wxString(_("Block")) , wxEmptyString, wxITEM_NORMAL);
     itemBlock->SetBitmap(wxBitmap(block_xpm));
     menu->Append(itemBlock);

     menu->Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&QBitmap::OnPopup, NULL, this);

     PopupMenu(menu); 
   }
   
   e.Skip();
 }

 void
  QBitmap::OnLeaveWindow(wxMouseEvent& e)
 {
   wxString name = GetName();

   wxBitmap bitmap;

   if (!name.Cmp("bitmap_minus")) {

     bitmap = wxBitmap(minus_xpm); 
      
   } else if (!name.Cmp("bitmap_close") || !name.Cmp("chat_close")) {

     bitmap = wxBitmap(close_xpm);
   
   } else {
      return;
   }

   wxClientDC dc(this);

   dc.Clear();

   dc.DrawBitmap(bitmap, 0, 0, true);

   GetParent()->RefreshRect(GetRect());

   e.Skip();
 }

 void
  QBitmap::OnPopup(wxMouseEvent& e)
 {
   if (!GetName().Cmp("bitmap_buddy")) { 

    switch(e.GetId())
    {
     case POPUP_BUDDY_TAG:
     {
       ((IMBuddy *)m_data)->b_flag |= 0x01;
       break;
     }

     case POPUP_BUDDY_AUTOREPLY:
     {
       AutoReply *ar = new AutoReply(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(350,250), wxCLIP_CHILDREN|wxNO_BORDER|wxTAB_TRAVERSAL);

       wxPoint position = this->ClientToScreen(wxPoint(0 + GetBitmap().GetWidth(), 0 + GetBitmap().GetHeight()));

       ar->Move(position);
      
       ar->Show();

       break;
     }
    }
   }
 }

 void
  QBitmap::OnLeftDClick(wxMouseEvent& WXUNUSED(e))
 {
   if (!GetName().CmpNoCase("bitmap_buddy")) { /* Jabber buddy activated */

    IMBuddy *buddy = (IMBuddy *) m_data;

    if (!buddy->b_tab) { /* if the tab for this contact is not present */

      buddy->b_tab = new ChatDialog(wxGetApp().m_frame->p2,
                                    wxID_ANY,
                                    buddy->b_name ? *(buddy->b_name) : *(buddy->b_id),
                                    wxDefaultPosition,
                                    wxSize(350, 300),
                                    0,
                                    buddy,
                                    wxGetApp().m_frame->p2);
    }

    if (!(buddy->b_tab->m_point).x ||
        !(buddy->b_tab->m_point).y ) {
  
      buddy->b_tab->m_point = GetParent()->GetParent()->GetParent()->ClientToScreen(wxPoint(0,0));

      (buddy->b_tab->m_point).x -= 375;

      (buddy->b_tab->m_point).x < 0 ? (buddy->b_tab->m_point).x = 20 : 1;

      (buddy->b_tab->m_point).y < 0 ? (buddy->b_tab->m_point).y = 20 : 1;
    }

    buddy->b_tab->Move(buddy->b_tab->m_point);

    if (buddy->b_tab->IsIconized()) {
      buddy->b_tab->Maximize(false);
    } else {
      buddy->b_tab->Show();
    }

    buddy->b_tab->ch_chat->SetFocus();

    buddy->b_tab->parse_chat_transcript();
   }
 }

 void
  QTab::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(e))
 {
   // don't call event.Skip() here...
 }

 void 
  QTab::OnMotion (wxMouseEvent& e)
 {
   if (HasCapture() && bStartSnip) {
     m_currentpoint = ClientToScreen(e.GetPosition());
     wxRect newrect(m_anchorpoint , m_currentpoint) ;
     wxScreenDC sdc;
     wxDCOverlay overlaydc(m_overlay, &sdc);
     wxPen pen(*wxRED, 1.8); 
     sdc.SetPen(pen);
     sdc.SetBrush(*wxTRANSPARENT_BRUSH);
     overlaydc.Clear();
     sdc.DrawRectangle(newrect);
     return;
   }
 }

 void
  QTab::OnLeftDown(wxMouseEvent& e)
 {
   if (!GetName().CmpNoCase("punchline")) {

     SetFocus();
   
     GetParent()->Freeze();

     wxString status = GetLabel();

     Hide();

     ((Jabber *)GetParent())->j_text->Clear();

     ((Jabber *)GetParent())->j_text->WriteText(status);

     ((Jabber *)GetParent())->j_text->SelectAll();

     ((Jabber *)GetParent())->j_text->Show();

     ((Jabber *)GetParent())->j_text->SetFocus();

     ((Jabber *)GetParent())->j_sizer->Layout();

     GetParent()->Thaw();

   } else if (!GetName().Cmp("snip")) {

       m_currentpoint = m_anchorpoint = ClientToScreen(e.GetPosition());
       bStartSnip = HasCapture();
    
   } else if (!GetName().Cmp("chat_g") ||
              !GetName().Cmp("chat_f")) {

      SetFocus();
      
      if (m_check) {
        m_check  = false;
        m_bitmap = checkdim_xpm;
      } else {
        m_check = true;
        m_bitmap = check_xpm;        
      }
      
      wxMouseEvent e;
      OnLeaveWindow(e);
   }
 }

 void
  QTab::OnLeftUp(wxMouseEvent& e) 
 {
   NP *np = wxGetApp().m_frame;

   if (!GetName().Cmp("menu")) { /* main menu tab */ 
   
    wxMenu *menu = new wxMenu();
    
    wxMenuItem *itemNew = 0;
    
    if (np->p2 && np->p2->IsShown()) {
      itemNew = new wxMenuItem(menu, POPUP_MAIN_NEW, wxString( _("New Session") ) , wxEmptyString, wxITEM_NORMAL);
      itemNew->SetBitmap(wxBitmap(plus_xpm));
      menu->Append(itemNew);
    }
    
    wxMenuItem *itemColour = new wxMenuItem(menu, POPUP_MAIN_COLOUR, wxString( _("Colour") ) , wxEmptyString, wxITEM_NORMAL);
    itemColour->SetBitmap(wxBitmap(colour_xpm));
    menu->Append(itemColour);

    wxMenuItem *itemAbout = new wxMenuItem(menu, POPUP_MAIN_ABOUT, wxString( _("About") ) , wxEmptyString, wxITEM_NORMAL );
    itemAbout->SetBitmap(wxBitmap(netpad20_xpm)); 
    menu->Append(itemAbout);

    wxMenuItem *itemExit = new wxMenuItem(menu, POPUP_MAIN_EXIT, wxString( _("Exit") ) , wxEmptyString, wxITEM_NORMAL );
    itemExit->SetBitmap(wxBitmap(exit20_xpm)); 
    menu->Append(itemExit);

   #ifdef __WXMSW__
    if (itemNew) itemNew->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
    itemColour->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
    itemAbout->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
    itemExit->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
   #endif

    menu->Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &QTab::OnPopup, NULL, this);

    PopupMenu(menu);

    menu->UpdateUI();

  } else if (!GetName().Cmp("yes")) {

  
  } else if (!GetName().Cmp("no")) {


  } else if (!GetName().Cmp("snip")) {

     OutputDebugStringW(L"OnLeftUp\n");
     
     static SeeThroughFrame *seeThroughFrame;
     
     if (!HasCapture()) {

       int w, h;
       
       wxDisplaySize(&w, &h);
       
       m_bitmap = snip2_xpm;
       seeThroughFrame = new SeeThroughFrame();
       seeThroughFrame->SetParent(this);
       seeThroughFrame->SetSize(wxGetDisplaySize());
       SetBackgroundStyle(wxBG_STYLE_COLOUR);
       seeThroughFrame->SetTransparent(65);
       seeThroughFrame->Show(true);
       
       m_overlay.Reset();

       CaptureMouse();  

     } else {

       if (seeThroughFrame) {
         seeThroughFrame->Close(true);
         seeThroughFrame = NULL;
       }
       
       ReleaseCapture();

       wxScreenDC dc;

       wxDCOverlay overlaydc(m_overlay, &dc);

       overlaydc.Clear();

       m_bitmap = snip_xpm;
       
       if (((ChatDialog *)GetParent())->buddy) {
       
         ((ChatDialog *)GetParent())->buddy->b_snip = new wxImage();
    
         get_screen(((ChatDialog *)GetParent())->buddy->b_snip, m_anchorpoint, m_currentpoint);

         ((ChatDialog *)GetParent())->ch_chat->WriteText("..snip..");
    
         wxCommandEvent ee;
    
         ((ChatDialog *)GetParent())->OnTextEnter(ee);   
       }
     }
   
  } else if (!GetName().Cmp("ch_menu") ) {


  } else if (!GetName().CmpNoCase("status")) {

    connection *c = (connection *) m_data;
    
    wxMenu *menu = new wxMenu();

    wxMenuItem *itemBusy = new wxMenuItem(menu, POPUP_PRESENCE_BUSY, wxString( _("Busy") ) , wxEmptyString, wxITEM_NORMAL );
    itemBusy->SetBitmap(wxBitmap(red_xpm));
    menu->Append(itemBusy);

    wxMenuItem *itemAvailable = new wxMenuItem(menu, POPUP_PRESENCE_AVAILABLE, wxString( _("Available") ) , wxEmptyString, wxITEM_NORMAL );
    itemAvailable->SetBitmap(wxBitmap(green_xpm));
    menu->Append(itemAvailable);

    wxMenuItem *itemAway = new wxMenuItem(menu, POPUP_PRESENCE_AWAY, wxString( _("Away") ) , wxEmptyString, wxITEM_NORMAL );
    itemAway->SetBitmap(wxBitmap(orange_xpm));
    menu->Append(itemAway);

    wxMenuItem *itemInvisible = new wxMenuItem(menu, POPUP_PRESENCE_INVISIBLE, wxString( _("Invisible") ) , wxEmptyString, wxITEM_NORMAL );
    itemInvisible->SetBitmap(wxBitmap(invisible_xpm));
    menu->Append(itemInvisible);

    if (((wxString *)c->j_jid)->Contains("chat.facebook.com")) {
      itemBusy->Enable(false);
      itemAvailable->Enable(false);
      itemAway->Enable(false);
      itemInvisible->Enable(false);
    }    

    wxMenuItem *itemSOut = new wxMenuItem(menu, POPUP_PRESENCE_LOGOUT, wxString( _("Sign out") ) , wxEmptyString, wxITEM_NORMAL );
    itemSOut->SetBitmap(wxBitmap(exit_xpm));
    menu->Append(itemSOut);

   #ifdef __WXMSW__
    itemAvailable->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
    itemAway->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
    itemInvisible->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
    itemSOut->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
   #endif

    menu->Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&QTab::OnPopup, NULL, this);
   
    PopupMenu (menu);

  } else {
     e.Skip();
  }
 }

 void QTab::mouseWheelMoved(wxMouseEvent& WXUNUSED(e)) {}
 void QTab::rightClick(wxMouseEvent& WXUNUSED(e)) {}
 void QTab::keyPressed(wxKeyEvent& WXUNUSED(e)) {}
 void QTab::keyReleased(wxKeyEvent& WXUNUSED(e)) {}
 void QTab::OnRightDown(wxMouseEvent& WXUNUSED(e)) { }
 void QTab::OnSetFocus(wxFocusEvent& e) { e.Skip(); }

 void 
  QTab::OnPopup (wxMouseEvent& e)
 {
  if (!GetName().Cmp("menu")) /* main menu tab */
  {
   switch(e.GetId())
   {
    case POPUP_MAIN_NEW: 
    {
      NP *m_frame = new NP(wxGetApp().m_frame);

      m_frame->Centre();

      m_frame->Show();    
    
      break;
    }    

    case POPUP_MAIN_COLOUR: 
    {
     #ifdef __WXMSW__
      CHOOSECOLOR cc;
      static COLORREF acrCustClr[16];
      static DWORD rgbCurrent = g_colour.GetRGB();

      ZeroMemory(&cc, sizeof(cc));

      cc.lStructSize = sizeof(cc);
      cc.lpCustColors = (LPDWORD) acrCustClr;
      cc.rgbResult = rgbCurrent;
      cc.hwndOwner = GetHWND();
      cc.Flags = CC_FULLOPEN | CC_RGBINIT;
 
      if (ChooseColor(&cc)==TRUE) 
      {
        rgbCurrent = cc.rgbResult;    
                
        g_colour.SetRGB(rgbCurrent);    
        
        ((NP *)(wxGetApp().m_frame))->put_cfg("[Colour]", g_colour.GetAsString());         
        
        GetParent()->Refresh();
        GetParent()->Update();
      }
     #endif
      break;
    }

    case POPUP_MAIN_ABOUT:
    {
       ChatDialog *testDiag = new ChatDialog(wxGetApp().m_frame->p2,
                                    wxID_ANY,
                                    wxString("Test"),
                                    wxDefaultPosition,
                                    wxSize(350, 300),
                                    0,
                                    NULL,
                                    wxGetApp().m_frame->p2);  
       testDiag->Show();                                    
    /*
      wxBitmap bitmap;

      bitmap.LoadFile("splash.bmp", wxBITMAP_TYPE_BMP);

      new wxSplashScreen(bitmap, 
                         wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT, 
                         6000, 
                         NULL, 
                         wxID_ANY, 
                         wxDefaultPosition, 
                         wxDefaultSize,
                         wxSIMPLE_BORDER|wxSTAY_ON_TOP);
     */                         
      break;
    }

    case POPUP_MAIN_EXIT:
    {
      GetParent()->Close(true);
      break;
    }
   }

  } else if (!GetName().Cmp("status")) {

    Jabber *j = (Jabber *) GetParent();

    connection *c = (connection *) this->m_data;

    if (!c) {
      return;
    }
     
    switch (e.GetId())
    {
     case POPUP_PRESENCE_AVAILABLE:
     {
       j->xmpp_status(c, "default");

       if (c->j_ss && ((((wxString *)(c->j_ss))->Find("invisible value=\"true\"") != wxNOT_FOUND) ||
                      (((wxString *)(c->j_ss))->Find("<show>dnd") != wxNOT_FOUND))) {
 
        if (((wxString *)(c->j_ss))->Find("<show>dnd") != wxNOT_FOUND) {

          /* replace first occurance of default in j_ss with dnd */

          ((wxString *)(c->j_ss))->Replace("dnd", "default", false);
        }

        ((wxString *)(c->j_ss))->Replace("invisible value=\"true\"", "invisible value=\"false\"");

        j->j_send(c, *((wxString *)(c->j_ss)));
       }

       break;
     }

     case POPUP_PRESENCE_BUSY:
     {
       /* first send out a presence */
      
       j->xmpp_status(c, "dnd", false);

       if (c->j_ss &&
           ((((wxString *)(c->j_ss))->Find("invisible value=\"true\"") != wxNOT_FOUND) ||
            (((wxString *)(c->j_ss))->Find("<show>default") != wxNOT_FOUND) ||
            (((wxString *)(c->j_ss))->Find("<show") != wxNOT_FOUND))) {

        if ((((wxString *)(c->j_ss))->Find("<show>default") != wxNOT_FOUND)||
            (((wxString *)(c->j_ss))->Find("<show") == wxNOT_FOUND)) {

           if (((wxString *)(c->j_ss))->Find("<show") == wxNOT_FOUND) {

             int nPos = ((wxString *)(c->j_ss))->Find((((wxString *)(c->j_ss))->AfterFirst('>')).AfterFirst('>'));

             ((wxString *)(c->j_ss))->insert(nPos, "<show>dnd</show>");

           } else {

             /* replace first occurance of default with dnd */

             ((wxString *)(c->j_ss))->Replace("default", "dnd", false);
           }
        }

        ((wxString *)(c->j_ss))->Replace("invisible value=\"true\"", "invisible value=\"false\"");

        j->j_send(c, *((wxString *)(c->j_ss)));
       }

       break;
     }

     case POPUP_PRESENCE_INVISIBLE:
     {
       if (c->j_ss) {
       
        assert(((wxString *)(c->j_ss))->Find("invisible value=") != wxNOT_FOUND);

        /* just set invisible to true and we'r done */

        if (c->j_ss && ((wxString *)(c->j_ss))->Find("invisible value=\"false\"") != wxNOT_FOUND) {

          ((wxString *)(c->j_ss))->Replace("invisible value=\"false\"", "invisible value=\"true\"");

          j->j_send(c, *((wxString *)(c->j_ss)));
        }

        j->xmpp_status(c, "default", true);
       }
       break;
     }    

     case POPUP_PRESENCE_AWAY:
     {
      /*
       * Note: Because Google Talk interprets the 'away' status as idle, and idleness is a per-connection property, you 
       * cannot set an 'away' status using the shared status method. To set an idle status message, send a standard 
       * <presence> stanza. check if we are transitioning from invisible
       */

       j->xmpp_status(c, "away");

       if (c->j_ss && ((wxString *)(c->j_ss))->Find("invisible value=\"true\"") != wxNOT_FOUND) {

         ((wxString *)(c->j_ss))->Replace("invisible value=\"true\"", "invisible value=\"false\"");

         j->j_send(c, *((wxString *)(c->j_ss)));
       }

       break;
     }
     
     case POPUP_PRESENCE_LOGOUT:
     {
       assert(j);

       /* End the current active session */

       j->end_stream((connection *)(j->j_status->m_data));
       
       IMBuddy *buddy = j->j_head;

       j->j_contacts->Freeze();

       while (buddy) {

         if (buddy->b_c == (connection *)j->j_status->m_data) {
           j->j_contacts->HideItem((buddy->b_isShown = false, buddy->b_i));  
         }

         buddy = buddy->next;
       }

       j->j_contacts->szWrap->Layout();

       j->j_contacts->Thaw();
        
       this->Refresh();

       break;
     }
   }

   j->j_szTB->Layout();

   //j->Refresh();

  } else {
    e.Skip();
  }
}

 void
  QTab::OnPaint(wxPaintEvent& WXUNUSED(e))
 { 
   wxPaintDC dc(this);
   Render(dc);
 }

 wxSize 
  QTab::DoGetBestSize() const
 {
   wxClientDC dc(const_cast<QTab*> (this));

   wxFont font(wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana"));

   dc.SetFont(font);

   wxSize size;

   /* calculate the width */

   if (m_bitmap && GetLabel().Len()) {

     wxBitmap bitmap(m_bitmap);

     size.IncBy(1 + 1 + bitmap.GetWidth() + 1 + dc.GetTextExtent(GetLabel().BeforeFirst('\n')).GetWidth() + 1 + 1, 0);

   } else if (!m_bitmap && GetLabel().Len()) {

      size.IncBy(1 + 1 + dc.GetTextExtent(GetLabel().BeforeFirst('\n')).GetWidth() + 1 + 1, 0);

   } else if (m_bitmap && !(GetLabel().Len())) {

      wxBitmap bitmap(m_bitmap);

      size.IncBy(1 + 1 + bitmap.GetWidth() + 1 + 1, 0);
   }

   /* calculate the height */

   if (m_bitmap && !(GetLabel().Len())) {

     wxBitmap bitmap(m_bitmap);

     size.IncBy(0, bitmap.GetHeight());

   } else if (!m_bitmap && GetLabel().Len()) {

     size.IncBy(0, dc.GetTextExtent(GetLabel().BeforeFirst('\n') ).GetHeight());

   } else if (m_bitmap && GetLabel().Len()) {

     wxBitmap bitmap(m_bitmap);

     size.IncBy(0, dc.GetTextExtent(GetLabel().BeforeFirst('\n')).GetHeight() < bitmap.GetHeight() ? bitmap.GetHeight() : dc.GetTextExtent(GetLabel().BeforeFirst('\n')).GetHeight());
   }

   size.IncBy(0, 2 + 2);

   if (size.GetWidth() > ((GetParent()->GetSize()).GetWidth()/2)) {

     /* make the width only as much as half of the parent */

     size.SetWidth(((GetParent()->GetSize()).GetWidth()/2));
   }

   return size;
 }

 void
  QTab::Render (wxDC& dc)
 {
   wxString label = GetLabel();

   dc.SetBackgroundMode(wxTRANSPARENT);
   dc.SetBackground(*wxTRANSPARENT_BRUSH);
  
   wxFont font(wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana")); 

   if (m_underline) {

     font.SetUnderlined(true);

     dc.SetTextForeground (m_textcolourhighlight);

   } else {

     dc.SetTextForeground (m_textcolour);
   }

   dc.SetFont(font);

   wxSize size = DoGetBestSize();

   if (m_bitmap) {

     wxBitmap bitmap(m_bitmap);

     if (m_direction) {

       dc.DrawBitmap(bitmap, wxPoint(1 + 1, (size.GetHeight() - bitmap.GetHeight())/2), true);

       if (label.Len()) {

         dc.DrawText (label,
                      wxPoint(1 + 1 + bitmap.GetWidth() + 1,
                             (size.GetHeight() - dc.GetTextExtent(label.BeforeFirst('\n')).GetHeight())/2));
       }

     } else {

       if (label.Len()) {

         dc.DrawText(label,
                     wxPoint(1 + 1,
                             (size.GetHeight() - dc.GetTextExtent(label.BeforeFirst('\n')).GetHeight())/2));

       }

       dc.DrawBitmap(bitmap,
                     wxPoint(1 + 1 + dc.GetTextExtent(label.BeforeFirst('\n')).GetWidth() + 1,
                             (size.GetHeight() - bitmap.GetHeight())/2), true);

     }

   } else if (!m_bitmap && label.Len()) {

     /* only text */

     if (size.GetWidth() < dc.GetTextExtent(label.BeforeFirst('\n')).GetWidth()) {

       wxString partLabel;

       int i = 0;

       do {

         partLabel += label[i++];

       } while (dc.GetTextExtent(partLabel).GetWidth() < (size.GetWidth() - dc.GetTextExtent("...").GetWidth()));


       dc.DrawText(partLabel.BeforeLast(' '),
                   wxPoint(1 + 1,
                           (size.GetHeight() - dc.GetTextExtent(label.BeforeFirst('\n')).GetHeight())/2));

       dc.DrawText("...",
                   wxPoint(dc.GetTextExtent(partLabel.BeforeLast(' ')).GetWidth() + dc.GetTextExtent(" ").GetWidth(),
                           (size.GetHeight() - dc.GetTextExtent(label.BeforeFirst('\n')).GetHeight())/2));

     } else {

       dc.DrawText(label,
                   wxPoint(1 + 1,
                           (size.GetHeight() - dc.GetTextExtent(label.BeforeFirst('\n')).GetHeight())/2));

     }
   }
 }


 void
  QTab::OnEnterWindow(wxMouseEvent& WXUNUSED(e)) 
 {
   wxClientDC dc(this);

   wxSize size = DoGetBestSize();
 
   dc.SetBrush(*wxTRANSPARENT_BRUSH);

   if (m_active) {

     m_highlight ? dc.SetPen(*m_highlight) : dc.SetPen(*wxCYAN_PEN);

     if (m_round) {

       dc.DrawRoundedRectangle(0, 0, size.GetWidth(), size.GetHeight(), -0.15);

     } else {

       dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight()); 
     }
   }  
 }

 void
  QTab::OnLeaveWindow(wxMouseEvent& WXUNUSED(e))
 {
     GetParent()->RefreshRect(GetRect());
 }

 void
  QTab::SetLabel(const wxString& label)
 {
   wxWindow::SetLabel(label);

   this->SetSize(DoGetBestSize());

   Refresh();
 }

 void
  QTab::OnKillFocus(wxFocusEvent& e)
 {
   GetParent()->RefreshRect(GetRect());
   e.Skip();
 }

 void QTab::OnEraseBackground(wxEraseEvent&){}
 void QTab::OnChar(wxKeyEvent& e) { e.Skip(); }

 int
  Qlist::GetItemCount()
 { 
   return l_count;
 }

 void 
  Qlist::OnLeftDown(wxMouseEvent& e)
 {
   Jabber *j = (Jabber *) GetParent();
   
   if (j->j_hover && j->j_sizer->IsShown(j->j_szTB)) {
     wxMouseEvent ee;
     e.SetId(POPUP_TITLE_SESSION);
     OnPopup(e);
   }
   e.Skip();
 }

 void 
  Qlist::OnRightUp(wxMouseEvent& e) 
 {
   wxMenu menu;

   Jabber *j = (Jabber *) GetParent();

   wxMenuItem *itemRefresh = new wxMenuItem(&menu, POPUP_REFRESH_ROSTER, wxString(_("Refresh")) , wxEmptyString, wxITEM_NORMAL);
   menu.Append(itemRefresh);
       
       #ifdef __WXMSW__
        itemRefresh->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
       #endif  
   
   wxMenuItem *itemTitle = new wxMenuItem(&menu, wxID_ANY, wxString(_("Tool bar")) , wxEmptyString, wxITEM_CHECK);

   wxMenu *submenu = new wxMenu();   

   for (int i=0; i < MAX_SESSIONS; i++) {
     if (c_list[i].m_state) {
       wxMenuItem *itemSession = new wxMenuItem(&menu, POPUP_TITLE_SESSION+i, ((wxString *)(c_list[i].m_user))->BeforeFirst('@') + "@" + wxString(c_list[i].m_host), wxEmptyString, wxITEM_CHECK);
       submenu->Append(itemSession);
       #ifdef __WXMSW__
        itemSession->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
       #endif          
     }
   }

   submenu->AppendSeparator();

   wxMenuItem *itemHide = new wxMenuItem(&menu, POPUP_HIDE_TITLE, wxString(_("Hide")) , wxEmptyString, wxITEM_CHECK);
   submenu->Append(itemHide);    

   itemTitle->SetSubMenu(submenu);

   menu.Append(itemTitle);

   wxMenuItem *itemShowonline = new wxMenuItem(&menu, POPUP_SHOW_ONLINE, wxString(_("Hide offline friends")) , wxEmptyString, wxITEM_CHECK);
   menu.Append(itemShowonline);

   wxMenuItem *itemStatusAlerts = new wxMenuItem(&menu, POPUP_STATUS_ALERTS, wxString(_("Status change alerts")) , wxEmptyString, wxITEM_CHECK);
   menu.Append(itemStatusAlerts);

   #ifdef __WXMSW__
    itemStatusAlerts->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
    itemShowonline->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
    itemTitle->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
    itemHide->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana") ) );
   #endif   
   
   
   itemShowonline->Check(j->j_hideoffline);
   itemHide->Check(!(j->j_sizer->IsShown(j->j_szTB)));
   itemStatusAlerts->Check(j->g_alert);

   menu.Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&Qlist::OnPopup, NULL, this);

   PopupMenu(&menu); 

   e.Skip(); 
 }

 void
  Qlist::OnPopup(wxMouseEvent& e)
 {
   Jabber *j = (Jabber *) GetParent();
   static int lastSelected;

   IMBuddy *buddy = 0;

   if ((e.GetId() >= POPUP_TITLE_SESSION) &&
       (e.GetId() < POPUP_TITLE_SESSION + MAX_SESSIONS)) 
   {
      j->Freeze();
      
      j->GetSizer()->Show(j->j_szTB, true, false);

      lastSelected = e.GetId() - POPUP_TITLE_SESSION;

      j->update_title_bar(NULL, c_list + lastSelected);

      j->process_status(c_list + lastSelected);

      j->Thaw();
      
      j->GetSizer()->Layout();

      return;
   }
   
   switch (e.GetId())
   {   
     case POPUP_HIDE_TITLE:
     {
      if (j->GetSizer()->IsShown(j->j_szTB)) {
         /* hide */
         j->GetSizer()->Show(j->j_szTB, false, false);
         j->j_search->Refresh();

      } else {
         /* show */
         j->Freeze();
         j->GetSizer()->Show(j->j_szTB, true, false);
         j->Thaw();
         j->update_title_bar(0, c_list + lastSelected);
      }

      j->GetSizer()->Layout();

      break;
     }

     case POPUP_REFRESH_ROSTER:
     {
      /*
       * traverse the buddy list and update all the item images based on their status 
       * 0x00-offline, 0x01-available, 0x10-away, 0x11-busy 
       */ 
 
       j->j_contacts->Freeze();

       buddy = j->j_head;

       while (buddy) {
         buddy = buddy->next;
       } 
       
       j->j_contacts->Thaw();

       j->j_contacts->Scroll(0, 0);
       
       szWrap->Layout();

       this->Refresh();
       
       break;
     }

     case POPUP_STATUS_ALERTS:
     {
       j->g_alert ?  j->g_alert = false : j->g_alert = true;

       break;
     }

     case POPUP_SHOW_ONLINE:
     {
      /* flip and then act on it */
      
      j->j_hideoffline = !j->j_hideoffline;

      /* hide offline contacts */
      
      if (j->j_hideoffline)
      {
        buddy = j->j_head;

        Freeze();

        while (buddy) {

          if (buddy->b_status <= 0) {
            HideItem((buddy->b_isShown = false, buddy->b_i));  
          }

          buddy = buddy->next;
        }

        szWrap->Layout();

        this->Refresh();

        Thaw();

      } else {

        /* show all the contacts */

        buddy = j->j_head;

        Freeze();

        while (buddy) {

          /* show and do not layout the wrap sizer */

          ShowItem(buddy->b_i, false); 

          buddy = buddy->next;
        }

        szWrap->Layout();

        this->Refresh();

        Thaw();
      }
     }

     break;
   }
 }

 wxSize 
  Qlist::DoGetBestSize() const
 {
   return GetParent()->GetSize();
 }

 Qlist::Qlist(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) 
      : wxScrolledWindow(parent, id, pos, size, style)
 {
   szWrap = new wxWrapSizer(wxHORIZONTAL);
   
   this->SetSizer(szWrap);

   this->Layout();

   szWrap->Fit(this);
    
   l_count = 0;

   m_autoreply = 0;

   SetScrollRate(0,5);

   this->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(Qlist::OnRightUp));
   this->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(Qlist::OnLeftDown));
 }

 int 
  Qlist::InsertItem(wxString& upperlabel, wxString lowerlabel, wxString& tip, const char **bitmap)
 {
   wxBoxSizer* szItem  = new wxBoxSizer(wxHORIZONTAL);
  
   QBitmap *q_image = new QBitmap(this, wxID_ANY, wxBitmap(bitmap), wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW, "bitmap_buddy");
   q_image->SetToolTip(tip);
 
   szItem->Add(q_image, 0, wxALIGN_CENTER_VERTICAL, 5);
  
   wxBoxSizer* bSizer3;
   bSizer3 = new wxBoxSizer(wxVERTICAL);
  
   wxStaticText *q_name = new wxStaticText(this, wxID_ANY, upperlabel, wxDefaultPosition, wxSize(100,-1), 0|wxST_ELLIPSIZE_END);
   q_name->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana")));
   q_name->Wrap(-1);

   bSizer3->Add(q_name, 0, wxEXPAND, 5);
  
   wxStaticText *q_punch = new wxStaticText (this, wxID_ANY, lowerlabel, wxDefaultPosition, wxSize(100,-1), 0|wxST_ELLIPSIZE_END);
   q_punch->SetFont(wxFont(wxNORMAL_FONT->GetPointSize()-1, 70, 90, 90, false, wxT("Verdana")));
   q_punch->Wrap(100);

   q_punch->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW));
  
   bSizer3->Add(q_punch, 0, 0, 5);

   if (!lowerlabel.Len()) {
     bSizer3->Hide(q_punch);
   }

   wxBoxSizer* szLast  = new wxBoxSizer(wxHORIZONTAL);

   QBitmap *q_status = new QBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW, "bitmap_status");
   QBitmap *q_device = new QBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW, "bitmap_device");

   szLast->Add(q_status, 0, wxTOP|wxEXPAND, 5);
   szLast->Add(q_device, 0, wxLEFT|wxEXPAND, 5);

   bSizer3->Add(szLast, 0, wxEXPAND, 5);

   szItem->Add(bSizer3, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 5);
  
   szWrap->Add(szItem, 0, wxALL, 12);

   return (l_count++);
 }

 void
  Qlist::SetItemTip(int index, wxString& tip)
 {
   assert((index >= 0) && (index <= l_count)) ;

   wxSizerItem *sizerItem = szWrap->GetItem(index);

   assert(sizerItem->IsSizer());

   wxSizer *itemSizer = sizerItem->GetSizer(); /* this is tracking a sizer.. extract it */

   assert(!itemSizer->IsEmpty());

   sizerItem = itemSizer->GetItem((size_t)0);

   QBitmap *bitmap = (QBitmap *)sizerItem->GetWindow();

   bitmap->SetToolTip(tip);
 }

 void
  Qlist::SetItemTextColour(int index, wxColour& colour, int nRow)
 {
   assert((index >= 0) && (index <= l_count)) ;

   wxSizerItem *sizerItem = szWrap->GetItem(index);

   assert(sizerItem->IsSizer());

   wxSizer *itemSizer = sizerItem->GetSizer(); /* this is tracking a sizer.. extract it */

   assert(!itemSizer->IsEmpty());

   sizerItem = itemSizer->GetItem((size_t)1);

   itemSizer = sizerItem->GetSizer();

   sizerItem = itemSizer->GetItem((size_t)nRow);

   QText *text = (QText *)sizerItem->GetWindow();

   text->SetForegroundColour(colour);

   text->Refresh();
 }

 void
  Qlist::SetItemStatusImage(int index, const char **status, wxString *resource)
 {
   assert((index >= 0) && (index <= l_count)) ;
 
   wxSizerItem *sizerItem = szWrap->GetItem(index);

   assert(sizerItem->IsSizer());

   wxSizer *itemSizer = sizerItem->GetSizer(); /* this is tracking a sizer.. extract it */

   assert(!itemSizer->IsEmpty());

   sizerItem = itemSizer->GetItem((size_t)1);

   itemSizer = sizerItem->GetSizer();

   sizerItem = itemSizer->GetItem((size_t)2);

   itemSizer = sizerItem->GetSizer();

   sizerItem = itemSizer->GetItem((size_t)0);

   QBitmap *q_status = (QBitmap *) sizerItem->GetWindow();

   q_status->SetBitmap(status);

   QBitmap *q_device;
   
   if (resource) {

     sizerItem = itemSizer->GetItem((size_t)1);

     q_device = (QBitmap *) sizerItem->GetWindow();

     if (resource->Contains("android")) {

       q_device->SetBitmap(android_xpm);

     } else if (resource->Contains("Talk")) {

       q_device->SetBitmap(gtalk_xpm);

     } else if (resource->Contains("gmail")) {

       q_device->SetBitmap(gmail_xpm);

     } else if (resource->Contains(" Mac") ||
                resource->Contains(" iP")) {

       q_device->SetBitmap(apple_xpm);

     } else if (resource->StartsWith("NP.")) {

       q_device->SetBitmap(netpad20_xpm);

     } else if (resource->Contains("facebook")) {

       q_device->SetBitmap(facebook_xpm);
     }
     q_device->Refresh();
   }
   
   /* layout the last row sizer */

   itemSizer->Layout();
 }

 void
  Qlist::SetItemText(int index, wxString& text, int nRow)
 {
   assert((index >= 0) && (index <= l_count)) ;

   assert(nRow < 2); 
 
   wxSizerItem *sizerItem = szWrap->GetItem(index);

   assert(sizerItem->IsSizer());

   wxSizer *itemSizer = sizerItem->GetSizer(); /* this is tracking a sizer.. extract it */

   assert(!itemSizer->IsEmpty());

   sizerItem = itemSizer->GetItem((size_t)1);

   itemSizer = sizerItem->GetSizer();

   sizerItem = itemSizer->GetItem((size_t)nRow);

   QText *punch = (QText *) sizerItem->GetWindow();

   if (text.Len()) {

     itemSizer->Show(punch);
     punch->SetLabel(text);

   } else {

     punch->SetLabel(wxEmptyString); 
     itemSizer->Hide(punch);
   }

   itemSizer->Layout();

   /* layout the item's top sizer */

   sizerItem = szWrap->GetItem(index);

   assert(sizerItem->IsSizer());

   sizerItem->GetSizer()->Layout(); 
 }

 void
  Qlist::HideItem(int index)
 {
   assert((index >= 0) && (index <= l_count)) ;

   szWrap->Hide((size_t)index);
 }

 void
  Qlist::ShowItem(int index, bool bLayout)
 {
   assert((index >= 0) && (index <= l_count)) ;

   szWrap->Show((size_t)index, true);

   if (bLayout) { 
     Freeze();
     szWrap->Layout();
     Refresh();
     Thaw();
   }
 }

 void
  Qlist::DeleteItem(int index)
 {
  assert((index >= 0) && (index <= l_count)) ;

  if (!szWrap->IsEmpty()) {

    szWrap->Hide((size_t)index);

    szWrap->Remove(index);

    l_count--;

    szWrap->Layout();

    this->Refresh();
  }
 }

 void 
  Qlist::DeleteAllItems(void * WXUNUSED(key)) 
 {
   Freeze();

   if (!szWrap->IsEmpty()) {

    for (int index = 0; index < l_count; index++) {

      szWrap->Hide((size_t)index);

      szWrap->Remove(index);
    }
   }

   l_count = 0;

   szWrap->Layout();

   this->Refresh();

   Thaw();
 }

 void * 
  Qlist::GetItemData(int index) 
 {
   assert((index >= 0) && (index <= l_count)) ;

   wxSizerItem *sizerItem = szWrap->GetItem(index);

   assert(sizerItem->IsSizer());

   wxSizer *itemSizer = sizerItem->GetSizer(); /* this is tracking a sizer.. extract it */

   assert(!itemSizer->IsEmpty());

   sizerItem = itemSizer->GetItem((size_t)0);

   QBitmap *bitmap = (QBitmap *)sizerItem->GetWindow();

   return bitmap->m_data;
 } 

 void
  Qlist::SetItemData(int index, void *data) 
 {
   assert((index >= 0) && (index <= l_count)) ;

   wxSizerItem *sizerItem = szWrap->GetItem(index);

   assert(sizerItem->IsSizer());

   wxSizer *itemSizer = sizerItem->GetSizer();

   assert(!itemSizer->IsEmpty());

   sizerItem = itemSizer->GetItem((size_t)0);

   QBitmap *bitmap = (QBitmap *)sizerItem->GetWindow();

   bitmap->m_data = data;
 }

 void
  Qlist::SetItemImage(int index, const char **image, wxImage *img)
 {
   assert((index >= 0) && (index <= l_count)) ;

   wxSizerItem *sizerItem = szWrap->GetItem(index);

   assert(sizerItem->IsSizer());

   wxSizer *itemSizer = sizerItem->GetSizer(); /* this is tracking a sizer.. extract it */

   assert(!itemSizer->IsEmpty());

   sizerItem = itemSizer->GetItem((size_t)0);

   QBitmap *bitmap = (QBitmap *) sizerItem->GetWindow();

   if (image) {
     bitmap->SetBitmap(wxBitmap(image));
   }

   if (img) {   
     bitmap->SetBitmap(wxBitmap(*img));
   }
   itemSizer->Layout();
   bitmap->Refresh();
 }

 Qlist::~Qlist() { }

 TransientPopup::~TransientPopup()
 {
 
 }

 void 
  TransientPopup::OnSetFocus(wxFocusEvent &e)
 {
   e.Skip();
 }

 void 
  TransientPopup::OnKillFocus(wxFocusEvent &e)
 {
  e.Skip();
 } 

 void 
  TransientPopup::Popup( wxWindow* WXUNUSED(focus) )
 {
   wxPopupTransientWindow::Popup();
 }

 void TransientPopup::OnDismiss()
 {
   wxPopupTransientWindow::OnDismiss();
 }

 bool TransientPopup::Show( bool show )
 {
  return wxPopupTransientWindow::Show( show );
 }

 bool TransientPopup::ProcessLeftDown(wxMouseEvent& e)
 {
   return wxPopupTransientWindow::ProcessLeftDown(e);
 }

 TransientPopup::TransientPopup(wxWindow *parent, wxString msg, char type) 
                :wxPopupTransientWindow(parent)
 {
   this->SetToolTip("");

   m_panel = new wxScrolledWindow(this, wxID_ANY);

   topSizer = new wxBoxSizer(wxVERTICAL);

   if (type == 1) { /* quick connect error message */

     m_panel->SetBackgroundColour( wxColor( 255, 99, 71 ) );

     m_text = new QText (m_panel, wxID_ANY, msg, wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW);

     topSizer->Add( m_text, 0, wxEXPAND|wxALL, 5 );

   } else if (type == 2) {

     m_panel->SetBackgroundColour( *wxWHITE );
   }

   m_panel->SetSizer(topSizer);
   topSizer->Fit(m_panel);
   topSizer->Fit(this);
 }

 ChatDialog::ChatDialog(wxWindow* parent,
                        wxWindowID id,
                        const wxString& title,
                        const wxPoint& pos,
                        const wxSize& size,
                        long style,
                        IMBuddy *buddy,
                        void *jabber) 
             : wxFrame(parent, id, title, pos, size, style)
 {
   this->SetSizeHints(wxDefaultSize, wxDefaultSize);

   this->SetBackgroundColour(*wxWHITE);
 
   this->buddy = buddy;
   this->jabber = jabber;
 
   bSizer1 = new wxBoxSizer(wxVERTICAL);
  
   bSizer2 = new wxBoxSizer(wxHORIZONTAL);
  
   ch_menu = new QTab(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTRANSPARENT_WINDOW, "", menu_xpm, "ch_menu", true);

   ch_menu->m_active = false;
   ch_menu->m_textcolour = *wxCYAN;

   bSizer2->Add(ch_menu, 0, wxLEFT|wxTOP|wxBOTTOM|wxALIGN_CENTER_VERTICAL, 5); 

   m_snip = new QTab(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTRANSPARENT_WINDOW, "", snip_xpm, "snip", true);   
   m_snip->m_round = false;
   m_snip->SetToolTip(_("New snip"));
   
   bSizer2->Add(m_snip, 0, wxLEFT|wxTOP|wxBOTTOM|wxALIGN_CENTER_VERTICAL, 5);    
   
   bSizer2->Add(0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5);

   wxBoxSizer *szMinMax = new wxBoxSizer(wxHORIZONTAL);
  
   ch_minus = new QBitmap(this, wxID_ANY, wxBitmap(minimize_xpm), wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW, "bitmap_minus");
   ch_minus->SetToolTip(_("Minimize"));
   szMinMax->Add(ch_minus, 0, wxALL|wxALIGN_BOTTOM, 5);

   ch_close = new QBitmap(this, wxID_ANY, wxBitmap(close_xpm), wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW, "chat_close");
   ch_close->SetToolTip(_("Close"));
   szMinMax->Add(ch_close, 0, wxTOP|wxBOTTOM|wxRIGHT|wxALIGN_BOTTOM, 5);

   bSizer2->Add(szMinMax, 0, 0|wxLEFT|wxBOTTOM, 5); 

   bSizer1->Add(bSizer2, 0, wxEXPAND, 5);

   bSizer3 = new wxBoxSizer(wxVERTICAL);

   bSizer4 = new wxBoxSizer(wxHORIZONTAL);

   ch_avatar = new QBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW, "bitmap_avatar");

   if (buddy && buddy->b_avatar) {
     ch_avatar->SetBitmap(wxBitmap(*(buddy->b_avatar)));
   }

   ch_avatar->Refresh();

   bSizer4->Add(ch_avatar, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxLEFT|wxRIGHT, 5);

   ch_avatar->Refresh();

   bSizer4->Add(0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5);

   wxBoxSizer* bSizer5;
   bSizer5 = new wxBoxSizer(wxVERTICAL);
  
   ch_fn = new QText(this, wxID_ANY, (buddy && buddy->b_name) ? *(buddy->b_name) : ( buddy ? *(buddy->b_id) : ""), wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW);
   ch_fn->Wrap(-1);
   ch_fn->SetFont(wxFont(wxNORMAL_FONT->GetPointSize() + 1, 70, 90, 91, false, wxT("Verdana")));
   bSizer5->Add(ch_fn, 0, wxALIGN_RIGHT|wxRIGHT|wxLEFT, 5);

   ch_fid = new wxStaticText(this, wxID_ANY, (buddy && buddy->b_name) ? *(buddy->b_id) : "", wxDefaultPosition, wxDefaultSize, 0);
   ch_fid ->Wrap(-1);

   ch_fid->SetFont(wxFont(wxNORMAL_FONT->GetPointSize() + 1, 70, 90, 91, false, wxT("Verdana")));
   ch_fid->SetForegroundColour(wxColour(34,34,255));
   bSizer5->Add(ch_fid, 0, wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT, 5);

   wxBoxSizer* bSizer6;
   bSizer6 = new wxBoxSizer(wxHORIZONTAL);
  
   ch_status = new QBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW);

   bSizer6->Add(ch_status, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5);
    
   bSizer5->Add(bSizer6, 1, wxALIGN_RIGHT, 5);

   bSizer4->Add(bSizer5, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5);

   bSizer3->Add(bSizer4, 0, wxEXPAND, 5);

   ch_splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE|wxSP_NOBORDER|wxNO_BORDER);

   ch_splitter->Connect(wxEVT_IDLE, wxIdleEventHandler(ChatDialog::c_splitterOnIdle), NULL, this);

   ch_up = new wxPanel(ch_splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
   ch_up->SetBackgroundColour(*wxWHITE);
 
   wxBoxSizer* bSizer7;
   bSizer7 = new wxBoxSizer(wxVERTICAL);

   ch_transcript = new wxRichTextCtrl(ch_up, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0|wxTE_READONLY|wxTE_AUTO_URL|wxVSCROLL|wxWANTS_CHARS|wxHSCROLL|wxNO_BORDER);
   ch_transcript->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana")));

   bSizer7->Add(ch_transcript, 1, wxEXPAND, 5);

   if (buddy) {
     parse_chat_transcript();
   }
   
   ch_up->SetSizer(bSizer7);
   ch_up->Layout();

   bSizer7->Fit(ch_up);

   ch_down = new wxPanel(ch_splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
   ch_down->SetBackgroundColour(*wxWHITE);
 
   wxBoxSizer* bSizer8;
   bSizer8 = new wxBoxSizer(wxVERTICAL);
  
   ch_chat = new wxRichTextCtrl(ch_down, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0|wxNO_BORDER|wxTE_AUTO_URL|wxWANTS_CHARS|wxTE_PROCESS_ENTER|wxVSCROLL);
   ch_chat->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana")));

   bSizer8->Add(ch_chat, 1, wxEXPAND, 5);
  
   ch_chat->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(ChatDialog::OnKeyDown), NULL, this);
   ch_chat->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(ChatDialog::OnTextEnter), NULL, this);

   ch_down->SetSizer(bSizer8);
   ch_down->Layout();
   bSizer8->Fit(ch_down);
   ch_splitter->SplitHorizontally(ch_up, ch_down, 0);

   bSizer3->Add(ch_splitter, 1, wxEXPAND, 5);

   bSizer1->Add(bSizer3, 1, wxALL|wxEXPAND, 5);
  
   this->SetSizer(bSizer1);
   this->Layout();
  
   this->Centre(wxBOTH);

   this->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(ChatDialog::OnClose));
   this->Connect(wxEVT_MOTION, wxMouseEventHandler(ChatDialog::OnMotion));
   this->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(ChatDialog::OnLeftDown));
   this->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(ChatDialog::OnLeftUp));
   this->Connect(wxEVT_PAINT, wxPaintEventHandler(ChatDialog::OnPaint));
   this->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(ChatDialog::OnLeftDClick));
   this->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(ChatDialog::OnKillFocus));
   this->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(ChatDialog::OnSetFocus));
 }

 void ChatDialog::OnKillFocus(wxFocusEvent& event) 
 {
   event.Skip();
 }

 void ChatDialog::OnSetFocus(wxFocusEvent& event) 
 {
   event.Skip();
 }

 ChatDialog::~ChatDialog()
 { 

 }

 void 
  ChatDialog::OnKeyDown(wxKeyEvent& e) 
 {
   if ((e.GetKeyCode() == WXK_NUMPAD_ENTER) || 
       (e.GetKeyCode() == WXK_RETURN)) {

     ch_chat->SetInsertionPointEnd();

   } else if (e.GetKeyCode() == WXK_ESCAPE) {

     Close(TRUE);
   }

   e.Skip(); 
 }

 void 
  ChatDialog::c_splitterOnIdle(wxIdleEvent& WXUNUSED(e))
 {
   ch_splitter->SetSashPosition(140);
   ch_splitter->SetSashSize(0);
   ch_splitter->Disconnect(wxEVT_IDLE, wxIdleEventHandler(ChatDialog::c_splitterOnIdle), NULL, this);
 }

 void 
  ChatDialog::OnClose(wxCloseEvent& e) 
 {
   if (buddy) {
    buddy->b_tab = 0;
   }
   e.Skip();
 }

 void 
  ChatDialog::OnLeftDClick(wxMouseEvent& WXUNUSED(e)) 
 {
   static bool border;

   border ? (SetWindowStyleFlag(wxCLIP_CHILDREN|wxNO_BORDER|wxTAB_TRAVERSAL) , border = 0) : 
           (SetWindowStyleFlag(wxCLIP_CHILDREN|wxRESIZE_BORDER|wxTAB_TRAVERSAL) , border = 1);
           
   Refresh();
 }

 void 
  ChatDialog::OnLeftUp(wxMouseEvent& WXUNUSED(e)) 
 {
   if (HasCapture()) {
     ReleaseMouse();
   }
 }

 void
  ChatDialog::OnPaint(wxPaintEvent& e) 
 {
   wxPaintDC dc(this);

   dc.GradientFillLinear(wxRect(bSizer2->GetSize()), wxColour(g_colour), *wxWHITE, wxSOUTH); 

   ch_menu->Refresh();

   e.Skip();
 }

 void 
  ChatDialog::OnLeftDown(wxMouseEvent& e)
 {
   CaptureMouse();
   wxPoint pos = ClientToScreen(e.GetPosition());
   wxPoint origin = GetPosition();
   int dx =  pos.x - origin.x;
   int dy = pos.y - origin.y;
   m_delta = wxPoint(dx, dy);
 }

 void 
  ChatDialog::OnMotion(wxMouseEvent& e)
 {
   wxPoint pt = e.GetPosition();
 
   int x, y;

   GetScreenPosition(&x, &y);

   /*
   wchar_t aaa[125];
   swprintf(aaa, L"x %d y %d\n", x, y);
   OutputDebugString(aaa);
   */

   if (HasCapture()   && 
       e.Dragging()   && 
       e.LeftIsDown()) {

     wxPoint point = ClientToScreen(pt);
     Move(m_point = wxPoint(point.x - m_delta.x, point.y - m_delta.y));
   }
 }

 void
  ChatDialog::parse_chat_transcript(wxString line)
 {
   ch_transcript->SelectNone();

   ch_transcript->SetInsertionPointEnd();

   if (!line.Len()) {

     ch_transcript->Clear();

     wxString transcript = *(buddy->b_chat);

     wxStringTokenizer tokens(transcript, "\n");

     while (tokens.HasMoreTokens()) {

       wxString line = tokens.GetNextToken(), rest;

       if (line.StartsWith("Me ", &rest)) { /* our ping */
 
         ch_transcript->BeginBold();
         ch_transcript->WriteText("Me: ");
         ch_transcript->EndBold();
         ch_transcript->WriteText(rest);
 
       } else if (line.StartsWith(buddy->b_name ? *(buddy->b_name) : *(buddy->b_id), &rest)) { /* partners ping */

         ch_transcript->BeginBold();
         ch_transcript->WriteText((buddy->b_name ? *(buddy->b_name) : *(buddy->b_id)) + wxString(": "));
         ch_transcript->EndBold();
         ch_transcript->WriteText(rest);

      } else {

         ch_transcript->WriteText(line);
      }

      ch_transcript->WriteText("\n");
    } /* while */

  } else { 

    wxString rest;

    if (line.StartsWith("Me ", &rest)) {  /* our ping */

      ch_transcript->BeginBold();
      ch_transcript->WriteText("Me: ");
      ch_transcript->EndBold();
      ch_transcript->WriteText(rest);

    } else if (line.StartsWith(buddy->b_name ? *(buddy->b_name) : *(buddy->b_id), &rest)) { 
    
      /* partners ping */

      ch_transcript->BeginBold();
      ch_transcript->WriteText((buddy->b_name ? *(buddy->b_name) : *(buddy->b_id)) + wxString(": "));
      ch_transcript->EndBold();
      ch_transcript->WriteText(rest);

    } else {
   
      ch_transcript->WriteText(line);
    }

    ch_transcript->WriteText("\n");   
  }

  ch_transcript->ScrollIntoView(ch_transcript->GetCaretPosition(), WXK_DOWN);
 }


 void
  ChatDialog::OnTextEnter(wxCommandEvent& WXUNUSED(e))
 {
   wxString text = (ch_chat->GetValue()).Trim();

   if (!text.Len()) {
     return;
   }

   assert (buddy);

   Jabber *j = (Jabber *)jabber;

   xml_entity_outbound(text);
   
   wxString message = "<message from='" +
                       *((wxString *)(buddy->b_c->j_jid))             +
                       wxString("' id='")                             +
                       wxString("sl3nx51f")                           +
                       wxString("' to='")                             +
                       *(buddy->b_id)                                 +
                       wxString("' type='chat' xml:lang='en'><body>") +
                       text + wxString("</body>");

   wxString snip, rleSnip;
   
   if (buddy->b_snip) {

     DWORD startTime = GetTickCount();
     
     /* b_snip->SaveFile(wxString("C:\\Users\\mamn\\Desktop\\x.png"), wxBITMAP_TYPE_PNG); */

     snip = wxBase64Encode((void *)buddy->b_snip->GetData(), (buddy->b_snip->GetWidth())*(buddy->b_snip->GetHeight())*3);

     logit_a("time taken for wxBase64Encode %d seconds", (GetTickCount()-startTime)/1000);
     
     rleSnip = rle_encode(snip, snip.Len());
     
     logit_a ("time taken for rle_encode %d savings %d bytes\n", (GetTickCount()-startTime)/1000, snip.Len() - rleSnip.Len());
     
     message.Append(wxString("<image xmlns='netpad:image'><data>") + 
                             rleSnip                               +
                             wxString("</data>")                   +
                             wxString("<width>")                   +
                             wxString::Format(wxT("%i"), buddy->b_snip->GetWidth()) +
                             wxString("</width>")                  +
                             wxString("<height>")                  +
                             wxString::Format(wxT("%i"), buddy->b_snip->GetHeight()) +
                             wxString("</height>")                 +                             
                             wxString("</image>"));

     delete buddy->b_snip, buddy->b_snip = 0;
   }

   message.Append("</message>");
   
   j->j_send(buddy->b_c, message);

   buddy->b_chat->Append("\n");

   wxString line;

  line.Append(wxString(_("Me")) + " ");

  if (text.Last() == '\n') {

   line.Append(text.RemoveLast());

  } else {

   line.Append(text);
  }

  line.Replace("&amp;", "&");
  line.Replace("&lt;", "<");
  line.Replace("&gt;", ">");
  line.Replace("&quot;", "\"");
  line.Replace("&apos;", "'");

  buddy->b_chat->Append(line);

  parse_chat_transcript(line);

  ch_chat->Clear();
 
  ch_chat->SetInsertionPoint(0);
 }

 AutoReply::AutoReply(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) 
          : wxDialog(parent, id, title, pos, size, style)
 {
   this->SetSizeHints(wxDefaultSize, wxDefaultSize);

   wxBoxSizer *bSizerAutoReply = new wxBoxSizer(wxVERTICAL);
 
   IMBuddy *buddy = (IMBuddy *)(((QBitmap *)GetParent())->m_data);

   Qlist *m_contacts = (Qlist *)(GetParent()->GetParent());

   bszTitle = new wxBoxSizer(wxHORIZONTAL);
 
   QTab *headline = new QTab(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTRANSPARENT_WINDOW, (buddy->b_name ? *(buddy->b_name) : *(buddy->b_id)), sync_xpm, "menu", true);

   bszTitle->Add(headline, 0, wxALL, 5);
   bSizerAutoReply->Add(bszTitle, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND, 5);

   m_message = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_NO_VSCROLL|wxNO_BORDER);
   m_message->SetFont(wxFont(wxNORMAL_FONT->GetPointSize()+2, 70, 90, 90, false, wxT("Verdana")));
   bSizerAutoReply->Add(m_message, 1, wxLEFT|wxRIGHT|wxEXPAND, 5);
  
   if (buddy->b_autoreply || 
       m_contacts->m_autoreply) {
     m_message->SetValue(buddy->b_autoreply ? *(buddy->b_autoreply) : *((wxString *)(m_contacts->m_autoreply)));
   }

   wxBoxSizer* bSizer;
   bSizer = new wxBoxSizer(wxHORIZONTAL);

   m_checkAll = new wxCheckBox(this, wxID_ANY, _("Do this for all contacts"), wxDefaultPosition, wxDefaultSize, 0|wxTRANSPARENT_WINDOW);
   m_checkAll->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana")));
   bSizer->Add(m_checkAll, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

   bSizer->Add(0, 0, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5);

   m_button = new wxButton(this, wxID_OK, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0|wxNO_BORDER);
   m_button->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Verdana")));
   m_button->SetDefault();

   m_button->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(AutoReply::OnAutoReply), NULL, this); 

   bSizer->Add(m_button, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);

   bSizerAutoReply->Add(bSizer, 0, wxEXPAND, 5);
	
   this->SetSizer(bSizerAutoReply);

   this->Layout();
	
   this->Centre(wxBOTH);

   this->Connect(wxEVT_MOTION, wxMouseEventHandler(AutoReply::OnMotion));
   this->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(AutoReply::OnLeftDown));
   this->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(AutoReply::OnLeftUp));
   this->Connect(wxEVT_PAINT, wxPaintEventHandler(AutoReply::OnPaint));
 }

 AutoReply::~AutoReply()
 {

 }

 void
  AutoReply::OnAutoReply(wxCommandEvent& e)
 { 
   IMBuddy *buddy = (IMBuddy *)(((QBitmap *)this->GetParent())->m_data);

   if ((m_message->GetValue()).Len()) {

     if (buddy->b_autoreply) {
       delete (buddy->b_autoreply);
       buddy->b_autoreply = 0;
     }

     buddy->b_autoreply = new wxString(m_message->GetValue());

     if (m_checkAll->IsChecked()) {
       ((Qlist *)this->GetParent()->GetParent())->m_autoreply = buddy->b_autoreply;
     }

   } else if (buddy->b_autoreply)  {
      delete (buddy->b_autoreply);
      buddy->b_autoreply = 0;
   }
   e.Skip(); 
 }

 void
  AutoReply::OnLeftUp(wxMouseEvent& WXUNUSED(e)) 
 { 
   if (HasCapture()) {
     ReleaseMouse(); 
   }
 }

 void
  AutoReply::OnPaint(wxPaintEvent& e) 
 { 
   wxPaintDC dc(this);

   dc.GradientFillLinear( wxSize(bszTitle->GetSize()), g_colour, *wxWHITE, wxSOUTH);

   e.Skip();
 }

 void
  AutoReply::OnLeftDown(wxMouseEvent& e)
 {
   CaptureMouse();
   wxPoint pos = ClientToScreen(e.GetPosition());
   wxPoint origin = GetPosition();
   int dx =  pos.x - origin.x;
   int dy = pos.y - origin.y;
   m_delta = wxPoint(dx, dy);
 }

 void
  AutoReply::OnMotion(wxMouseEvent& e)
 {
   wxPoint pt = e.GetPosition();

   if (HasCapture() && e.Dragging() && e.LeftIsDown()) {

     wxPoint pos = ClientToScreen(pt);

     Move(wxPoint(pos.x - m_delta.x, pos.y - m_delta.y));
   }
 }

 QLine::QLine() {}

 QLine::QLine(wxWindow  *parent,
              wxWindowID id,
              const wxPoint& pos,
              const wxSize& size,
              long style, int thick)
        : wxWindow (parent, id, pos, size, style)
 {
   this->thick = thick;
 }

 wxSize
  QLine::DoGetBestSize() const
 {
   return wxSize((GetParent()->GetSize()).GetWidth(), thick);
 }

 void
  QLine::OnPaint(wxPaintEvent& WXUNUSED(e))
 {
   wxPaintDC dc(this);
   dc.SetPen(wxPen(g_colour, thick));
   dc.DrawLine(0, 0, GetSize().GetWidth(), 0); 
 }

 void QLine::OnEraseBackground(wxEraseEvent&) {}

 IMPLEMENT_CLASS( TransientPopup, wxPopupTransientWindow )

 void
  show_error(wxWindow *parent, wxString msg, char type)
 {
   if (m_ErrPopUp) {
     delete (TransientPopup *) m_ErrPopUp;
   }

   m_ErrPopUp = new TransientPopup(parent, msg, type);
   wxPoint pos = parent->ClientToScreen(wxPoint(0,0));
   wxSize sz = parent->GetSize();
   ((TransientPopup *)m_ErrPopUp)->Position( pos, sz );
   ((TransientPopup *)m_ErrPopUp)->Popup( );
 }

 //////////////////////////////////////////////////////
 // Task bar methods
 //////////////////////////////////////////////////////

 wxMenu *
  TBIcon::CreatePopupMenu()
 {
    wxMenu *menu = new wxMenu;

    /* OSX has built-in quit menu for the dock menu, but not for the status item */

   #ifdef __WXOSX__ 
    if ( OSXIsStatusItem() )
   #endif
    {
        menu->Append(PU_SOUT, wxT("Sign Out"));
        menu->AppendSeparator();
        menu->Append(PU_OPEN, wxT("&Open"));
        menu->Append(PU_EXIT, wxT("E&xit"));
    }

    return menu;
 }

 void
  TBIcon::OnSignOut(wxCommandEvent&)
 {
   NP *np = wxGetApp().m_frame;

   if (np && np->p2) {
      for (int i = 0; i < MAX_SESSIONS; i++) {
        if (c_list[i].m_state) {
          ((Jabber *)(np->p2))->end_stream(c_list+i);
        }
      }
   }
 }

 void
  TBIcon::OnOpen(wxCommandEvent&)
 {
   NP *np = wxGetApp().m_frame;

   if (np) {
     np->Show(true);
   }
 }

 void
  TBIcon::OnExit(wxCommandEvent&)
 {
   NP *np = wxGetApp().m_frame;

   if (np) {
     np->Close(true);
   }
 }

 void 
  TBIcon::OnLeftDClick(wxTaskBarIconEvent&)
 {
   NP *np = wxGetApp().m_frame;

   if (np) {
     np->Show(true);
   }
 }

 /////////////////////////////////////////////
 // TaskBarBaloon
 /////////////////////////////////////////////

 TaskBarBaloon::TaskBarBaloon(wxString sTitle, wxString sMessage)
               : wxFrame(NULL,-1,wxT("no title"), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxSTAY_ON_TOP|wxFRAME_SHAPED|wxFRAME_NO_TASKBAR)
 {
    wxColour bgColour(255,255,231); /* yellow BG */

    this->SetBackgroundColour(bgColour);

    wxBoxSizer * mainSizer = new wxBoxSizer(wxVERTICAL);

    wxStaticText * title = new wxStaticText(this, -1, sTitle);
    wxFont titleFont = this->GetFont();
    titleFont.SetWeight(wxFONTWEIGHT_BOLD);
    title->SetFont(titleFont);

    mainSizer->Add(title, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5);

    title->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(TaskBarBaloon::OnClick), NULL, this );
    //title->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(TaskBarBaloon::OnEscape), NULL, this );

    wxStaticText * text = new wxStaticText(this, -1, sMessage);
    mainSizer->Add(text,1,wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 5);

    text->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(TaskBarBaloon::OnClick), NULL, this );
    //text->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(TaskBarBaloon::OnEscape), NULL, this );

    this->SetSizer(mainSizer);
    mainSizer->SetSizeHints( this );
 
    this->timer = new wxTimer(this, TIMER_BALOON);
 
    /** align the frame to the right bottom corner */

    this->Center();
    int iX = 0, iY = 0;
    this->GetPosition(&iX, &iY);
    iX = (iX * 2) - 2;
    iY = (iY * 2) - 2;
    this->Move(iX, iY);
 }

 void 
  TaskBarBaloon::OnClick(wxMouseEvent& WXUNUSED(e))
 {
   this->timer->Stop();
   this->timer->Start(iTimeout, wxTIMER_ONE_SHOT);
 }

 void
  TaskBarBaloon::OnPaint(wxPaintEvent& WXUNUSED(e))
 {
    wxPaintDC dc(this);
 
    int iWidth = 0, iHeight = 0;
    this->GetClientSize( &iWidth, &iHeight );
 
    wxPen pen(this->GetForegroundColour());
    dc.SetPen(pen);
 
    wxBrush brush(this->GetBackgroundColour());
    dc.SetBrush(brush);
 
    dc.Clear();
    dc.DrawRectangle(0,0,iWidth,iHeight);
 }

 /** closing frame at end of timeout */

 void
  TaskBarBaloon::OnTimerTick(wxTimerEvent & WXUNUSED(e))
 {
    this->Destroy();
 }

 /** showing frame and running timer */

 void
  TaskBarBaloon::showBaloon(unsigned int iTimeout)
 {
    this->Show(true);
    this->timer->Start(this->iTimeout = iTimeout, wxTIMER_ONE_SHOT);
 }

 SeeThroughFrame::SeeThroughFrame()
       : wxFrame(NULL,
                 wxID_ANY,
                 wxEmptyString,
                 wxDefaultPosition,
                 wxDefaultSize,
                 wxNO_BORDER|wxFULL_REPAINT_ON_RESIZE|wxSTAY_ON_TOP|wxBG_STYLE_TRANSPARENT),
         m_currentState(STATE_SEETHROUGH)
 {
    SetBackgroundColour(wxColour(255, 255, 255, 255));
 }

 /** xml entity refrence for special characters */

 void
  xml_entity_inbound (wxString& m)
 {
   m.Replace ("&amp;", "&");
   m.Replace ("&lt;", "<");
   m.Replace ("&gt;", ">");
   m.Replace ("&quot;", "\"");
   m.Replace ("&apos;", "'");
 }

 void
  xml_entity_outbound (wxString& m)
 {
   m.Replace ("&", "&amp;");
   m.Replace ("<", "&lt;");
   m.Replace (">", "&gt;");
   m.Replace ("\"", "&quot;");
   m.Replace ("'", "&apos;");
 }
